package com.inspur.neoinput.neo4j.controller;

import com.inspur.neoinput.common.entity.RestfulResult;
import com.inspur.neoinput.common.utils.Constants;
import com.inspur.neoinput.neo4j.entity.Code;
import com.inspur.neoinput.neo4j.service.ICodeService;
import lombok.extern.log4j.Log4j;
import org.neo4j.driver.v1.*;
import org.neo4j.graphdb.Label;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

import static org.neo4j.driver.v1.Values.parameters;

/**
 * 自动代码生成Controller
 * 
 * @author sun
 * @version 2018-06-01
 */
@RestController
@RequestMapping(value = "neo4j")
public class CodeController {
	
	@Autowired
	private ICodeService codeService;

	@Value("${neo4j.url}")
	private String url;
	@Value("${neo4j.username}")
	private String username;
	@Value("${neo4j.password}")
	private String password;

	/**
	 * 同步节点
	 */
	@RequestMapping(value = "creatNode")
	public String creatNode() {
		try {
			//同步节点方法
			codeService.inputMethod(url,username,password);
			return "节点同步成功";
		} catch (Exception e) {
		    e.printStackTrace();
			return "节点同步失败";
		}
    }

	/**
	 * 同步节点关系，需要先同步节点
	 */
	@RequestMapping(value = "creatRelation")
	public String creatRelation() {
		try {
			//同步关系方法
			codeService.inputRelation(url,username,password);
			return "关系同步成功";
		} catch (Exception e) {
			e.printStackTrace();
			return "关系同步失败";
		}

	}

	/**
	 * 同步所有节点后同步关系，前两个组合版
	 */
	@RequestMapping(value = "creatAll")
	public String creatAll() {
		try {
			//先同步节点，再同步关系
			codeService.inputMethod(url,username,password);
			codeService.inputRelation(url,username,password);
			return "节点同步成功";
		} catch (Exception e) {
			e.printStackTrace();
			return "节点同步失败";
		}
	}

	/**
	 * 删除所有关系
	 */
	@RequestMapping(value = "deleteRelation")
	public String deleteRelation() {
		try {
			codeService.deleteRelation(url,username,password);
			return "节点同步成功";
		} catch (Exception e) {
			e.printStackTrace();
			return "节点同步失败";
		}
	}




	@RequestMapping(value = "test")
	public void test(HttpServletRequest request, HttpServletResponse response) {
		RestfulResult restfulResult = new RestfulResult();
		try{
			Driver driver = codeService.createDrive(url,username,password);
			Session session = driver.session();
			session.run("CREATE (a:Person {name: {name}, title: {title}})",
					parameters("name", "Arthur001", "title", "King001"));

			StatementResult result = session.run("MATCH (a:Person) WHERE a.name = {name} " +
							"RETURN a.name AS name, a.title AS title",
					parameters("name", "Arthur001"));

			while (result.hasNext()) {
				Record record = result.next();
				System.out.println(record.get("title").asString() + " " + record.get("name").asString() + " " + record.get("id").asString());
			}

			session.close();
			driver.close();

		}catch(Exception e){
			restfulResult.setResult(Constants.RESULT_STATE_ERROR);
			restfulResult.setMessage(e.getMessage());
		}
		
//    	CommUtils.printDataJason(response, restfulResult);
	}

	@RequestMapping(value = "save")
	public void save(HttpServletRequest request, HttpServletResponse response,
                     @RequestBody Code code) {
    	
		RestfulResult restfulResult = new RestfulResult();
		
		try{	
			Driver driver = codeService.createDrive(url,username,password);
	        Session session = driver.session();
	        
	        StatementResult result =  session.run( "CREATE (a:" + code.getLabel() + " {" + code.getProperty() + "}) return a");
	        
	        while (result.hasNext())
	        {
	            Record record = result.next();
		        restfulResult.setData(record.fields().get(0).value().toString().replace("node<", "").replace(">", ""));
	        }
	        
	        session.close();
	        driver.close();
			
		}catch(Exception e){
			restfulResult.setResult(Constants.RESULT_STATE_ERROR);
			restfulResult.setMessage(e.getMessage());
		}
		
//    	CommUtils.printDataJason(response, restfulResult);
	}

	@RequestMapping(value = "update")
	public void update(HttpServletRequest request, HttpServletResponse response,
                       @RequestBody Code code) {
    	
		RestfulResult restfulResult = new RestfulResult();
		
		try{	
			Driver driver = codeService.createDrive(url,username,password);
	        Session session = driver.session();
	        
	        StatementResult result = session.run("MATCH (a:" + code.getLabel() + ") WHERE a." + code.getWhere() + " SET a." + code.getUpdate() + " return COUNT(a)");
	        
	        while (result.hasNext())
	        {
	            Record record = result.next();
		        restfulResult.setData(record.fields().get(0).value().toString());
	        }
	        
	        session.close();
	        driver.close();
			
		}catch(Exception e){
			restfulResult.setResult(Constants.RESULT_STATE_ERROR);
			restfulResult.setMessage(e.getMessage());
		}
		
//    	CommUtils.printDataJason(response, restfulResult);
	}

    @RequestMapping(value = "delete")
	public void delete(HttpServletRequest request, HttpServletResponse response,
                       @RequestBody Code code) {
		RestfulResult restfulResult = new RestfulResult();
		
		try{			
			Driver driver = codeService.createDrive(url,username,password);
	        Session session = driver.session();
	        session.run( "match (n) where ID(n) = " + code.getId() +" detach delete n");
	        
	        session.close();
	        driver.close();
			
		}catch(Exception e){
			restfulResult.setResult(Constants.RESULT_STATE_ERROR);
			restfulResult.setMessage(e.getMessage());
		}
		
//    	CommUtils.printDataJason(response, restfulResult);
	}

    @RequestMapping(value = "search")
	public void search(HttpServletRequest request, HttpServletResponse response,
                       @RequestBody Code code) {
		RestfulResult restfulResult = new RestfulResult();
		
		try{			
			Driver driver = codeService.createDrive(url,username,password);
	        Session session = driver.session();

	        StatementResult result = session.run("MATCH " + code.getProperty() +
	        									" MATCH " + code.getRelation() +
	        									" WHERE " + code.getWhere() +
	                                              " RETURN " + code.getResult());
	        List<String> resultList = new ArrayList<String>();
	        while ( result.hasNext() )
	        {
	            Record record = result.next();
	            resultList.add(record.get("id").toString() + " " + record.get("name").toString());
	        }
	        
	        session.close();
	        driver.close();
	        
	        restfulResult.setData(resultList);
			
		}catch(Exception e){
			restfulResult.setResult(Constants.RESULT_STATE_ERROR);
			restfulResult.setMessage(e.getMessage());
		}
		
//    	CommUtils.printDataJason(response, restfulResult);
	}

    @RequestMapping(value = "relate")
	public void relate(HttpServletRequest request, HttpServletResponse response,
                       @RequestBody Code code) {
		RestfulResult restfulResult = new RestfulResult();
		
		try{
			Driver driver = codeService.createDrive(url,username,password);
	        Session session = driver.session();
	        
	        session.run("MATCH (a:" + code.getNodeFromLabel() + "), (b:" + code.getNodeToLabel() + ") " +
	        		"WHERE ID(a) = " + code.getNodeFromId() + " AND ID(b) = " + code.getNodeToId()
	        		+ " CREATE (a)-[:" + code.getRelation() + "]->(b)");
	        
	        session.close();
	        driver.close();
			
		}catch(Exception e){
			restfulResult.setResult(Constants.RESULT_STATE_ERROR);
			restfulResult.setMessage(e.getMessage());
		}
		
//    	CommUtils.printDataJason(response, restfulResult);
	}

	//private static final String DB_PATH = "D:/neo4j/data/databases/graph.db";
	
	//GraphDatabaseService graphDb;
	
	/*@RequestMapping(value = "save")
	public void save(HttpServletRequest request, HttpServletResponse response,
			@RequestBody Code code) {
    	
		RestfulResult restfulResult = new RestfulResult();
		
		try{		
			if (graphDb == null)
				this.graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(new File(DB_PATH));
			
			registerShutdownHook(graphDb);
			
			Transaction tx = graphDb.beginTx();
		
			Node node = this.graphDb.createNode();
			Label label = DynamicLabel.label(code.getLabel());
			node.addLabel(label);
			node.setProperty("Name", code.getProperty());

            tx.success();
            
            restfulResult.setData(node.getId());
			
		}catch(Exception e){
			restfulResult.setResult(Constants.RESULT_STATE_ERROR);
			restfulResult.setMessage(e.getMessage());
		}
		
    	CommUtils.printDataJason(response, restfulResult);
	}*/
    
/*    private void registerShutdownHook(final GraphDatabaseService graphDB){
        //关闭寄存器
        Runtime.getRuntime().addShutdownHook(new Thread(){
            public void run(){
                graphDB.shutdown();
            }
        });
    }*/
}
class CaseLabels implements Label {
	private String name;

	public CaseLabels(String name) {
		this.name = name;
	}

	public String name() {
		return name;
	}
}